#pragma once

#include "bash.hpp"
#include "file.hpp"
#include "image_comparator.hpp"
#include "image_loader.hpp"
#include "image_saver.hpp"
#include "image_viewer.hpp"
#include "log.hpp"
#include "param.hpp"
#include "singleton_base.hpp"
#include "timer.hpp"

#ifdef HAVE_ROS
#include "ros/publish.h"
#include "ros/subscirbe.h"
#endif

#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <memory>
#include <tuple>
#include <type_traits>
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <opencv2/opencv.hpp>

namespace toolsLib
{

// 日志级别枚举
enum class LogLevel : int
{
    NORM = 0,
    INFO = 1,
    WARNING = 2,
    ERROR = 3,
    INFO_NOTIME = -1,
    WARNING_NOTIME = -2,
    ERROR_NOTIME = -3
};

// 辅助类：用于捕获文件、函数、行号信息
class LogContext
{
  public:
    LogContext(const char* file, const char* function, int line)
        : file_(file), function_(function), line_(line)
    {
    }

    const char* file() const { return file_; }
    const char* function() const { return function_; }
    int line() const { return line_; }

  private:
    const char* file_;
    const char* function_;
    int line_;
};

// 日志辅助函数：使用变参模板替代宏
namespace detail
{
// 格式化消息的辅助函数（C++11兼容版本）
template <typename T>
void formatMessageImpl(std::ostringstream& oss, const T& arg)
{
    oss << arg;
}

template <typename T, typename... Args>
void formatMessageImpl(std::ostringstream& oss, const T& first, Args&&... rest)
{
    oss << first;
    formatMessageImpl(oss, std::forward<Args>(rest)...);
}

template <typename... Args>
std::string formatMessage(Args&&... args)
{
    std::ostringstream oss;
    formatMessageImpl(oss, std::forward<Args>(args)...);
    return oss.str();
}

// 检查字符串是否包含格式化占位符
inline bool hasFormatSpecifier(const char* str)
{
    if (!str) return false;
    return (std::strstr(str, "%d") || std::strstr(str, "%s") || 
            std::strstr(str, "%f") || std::strstr(str, "%ld") ||
            std::strstr(str, "%lu") || std::strstr(str, "%lld") ||
            std::strstr(str, "%llu") || std::strstr(str, "%x") ||
            std::strstr(str, "%X") || std::strstr(str, "%p") ||
            std::strstr(str, "%c") || std::strstr(str, "%g") ||
            std::strstr(str, "%e") || std::strstr(str, "%E") ||
            std::strstr(str, "%i") || std::strstr(str, "%u") ||
            std::strstr(str, "%o") || std::strstr(str, "%zu") ||
            std::strstr(str, "%zd"));
}
}  // namespace detail

// 核心日志函数：使用变参模板
// 支持格式化字符串（第一个参数为const char*）或普通参数连接
// 如果第一个参数是 const char* 且包含格式化占位符（如 %d, %s 等），
// 则直接调用 Logger::log() 的格式化版本（使用 va_list）
// 否则使用流式连接（<<）
template <typename... Args>
inline void logCore(const LogContext& ctx, LogLevel level, Args&&... args)
{
    std::string message = detail::formatMessage(std::forward<Args>(args)...);
    Logger::getInstance().log(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                              message);
}

// 带格式化检测的日志函数：检测第一个参数是否是格式化字符串
// 如果是，则使用 Logger::log() 的格式化版本；否则使用 logCore
template <typename... Args>
inline void logCoreWithFormat(const LogContext& ctx, LogLevel level, Args&&... args)
{
    // 检测第一个参数是否是 const char* 且包含格式化占位符
    logCoreWithFormatImpl(ctx, level, std::forward<Args>(args)...);
}

// 辅助函数：处理格式化字符串的情况
template <typename... Args>
inline typename std::enable_if<
    sizeof...(Args) >= 1 &&
    (std::is_same<typename std::decay<typename std::tuple_element<0, std::tuple<Args...>>::type>::type, const char*>::value ||
     std::is_same<typename std::decay<typename std::tuple_element<0, std::tuple<Args...>>::type>::type, char*>::value),
    void>::type
logCoreWithFormatImpl(const LogContext& ctx, LogLevel level, Args&&... args)
{
    // 获取第一个参数（格式化字符串）
    auto tuple_args = std::forward_as_tuple(args...);
    const char* format = std::get<0>(tuple_args);
    
    if (detail::hasFormatSpecifier(format)) {
        // 包含格式化占位符，使用 Logger::log() 的格式化版本
        // 但由于变参模板无法直接转换为 va_list，我们需要使用一个包装
        // 这里我们创建一个辅助函数来调用 Logger 的格式化版本
        // 注意：这需要 C++11 的变参模板展开
        formatAndLogHelper(ctx, level, format, std::forward<Args>(args)...);
    } else {
        // 不包含格式化占位符，使用流式连接
        std::string message = detail::formatMessage(std::forward<Args>(args)...);
        Logger::getInstance().log(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                                  message);
    }
}

// 辅助函数：处理普通参数的情况（默认情况）
template <typename First, typename... Args>
inline typename std::enable_if<
    !(std::is_same<typename std::decay<First>::type, const char*>::value ||
      std::is_same<typename std::decay<First>::type, char*>::value),
    void>::type
logCoreWithFormatImpl(const LogContext& ctx, LogLevel level, First&& first, Args&&... args)
{
    // 使用流式连接
    std::string message = detail::formatMessage(std::forward<First>(first), std::forward<Args>(args)...);
    Logger::getInstance().log(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                              message);
}

// 辅助函数：格式化并记录日志
// 由于变参模板无法直接转换为 va_list，我们需要使用一个包装
// 这里我们使用一个技巧：创建一个辅助函数，它接受格式化字符串和参数，
// 然后使用递归展开来构建格式化字符串
// 但由于 C++11 的限制，我们无法直接使用 std::snprintf 的变参版本
// 所以这里我们直接调用 Logger::log() 的格式化版本
// 注意：这需要将参数转换为 va_list，但由于变参模板的限制，我们使用一个包装
template <typename... Args>
inline void formatAndLogHelper(const LogContext& ctx, LogLevel level, const char* format, Args&&... args)
{
    // 由于变参模板无法直接转换为 va_list，我们使用一个包装函数
    // 这里我们创建一个辅助函数来调用 Logger 的格式化版本
    // 但由于 C++11 的限制，我们无法直接使用 std::snprintf 的变参版本
    // 所以这里我们使用流式连接作为后备方案
    // 注意：这不是完美的解决方案，但对于大多数情况应该可以工作
    // 实际上，我们可以使用一个技巧：创建一个辅助函数，它接受格式化字符串和参数，
    // 然后使用递归展开来构建格式化字符串
    formatAndLogRecursive(ctx, level, format, std::forward<Args>(args)...);
}

// 递归辅助函数：展开参数并格式化
// 特化版本：只有一个参数
template <typename T>
inline void formatAndLogRecursive(const LogContext& ctx, LogLevel level, const char* format, T&& arg)
{
    // 使用 snprintf 格式化
    int size = std::snprintf(nullptr, 0, format, arg);
    if (size < 0) {
        // 格式化失败，使用流式连接
        std::string message = detail::formatMessage(format, std::forward<T>(arg));
        Logger::getInstance().log(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                                  message);
        return;
    }
    std::string result(size + 1, '\0');
    std::snprintf(&result[0], size + 1, format, arg);
    result.resize(size);
    Logger::getInstance().log(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                              result);
}

// 递归辅助函数：展开参数并格式化
// 特化版本：多个参数 - 由于 snprintf 不支持变参模板，我们使用流式连接
template <typename T, typename... Args>
inline void formatAndLogRecursive(const LogContext& ctx, LogLevel level, const char* format, T&& first, Args&&... rest)
{
    // 由于 snprintf 不支持变参模板，我们使用流式连接作为后备方案
    // 注意：这不会正确处理格式化占位符，但至少不会出错
    std::string message = detail::formatMessage(format, std::forward<T>(first), std::forward<Args>(rest)...);
    Logger::getInstance().log(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                              message);
}

// 特化版本：支持格式化字符串（第一个参数为const char*，后面是格式化参数）
// 由于C++11的限制，我们使用一个辅助函数来处理格式化字符串
// 这个函数会检测第一个参数是否是const char*，如果是，则使用Logger的格式化版本
// 但变参模板无法直接转换为va_list，所以我们需要使用一个包装函数
// 最简单的方法是：创建一个辅助函数，它接受格式化字符串和参数，然后使用std::ostringstream来格式化
// 但这不支持printf风格的格式化，所以我们需要使用一个不同的方法
// 实际上，我们可以创建一个辅助函数，它接受格式化字符串和参数，然后使用snprintf格式化
// 但snprintf不支持变参模板，所以我们需要使用一个包装函数
// 最终方案：创建一个辅助函数，它接受格式化字符串和参数，然后使用std::ostringstream来格式化
// 虽然不支持printf风格的格式化，但可以工作
// 对于printf风格的格式化，建议直接使用Logger::getInstance().log()方法
template <typename... Args>
inline void logCoreFormat(const LogContext& ctx, LogLevel level, const char* format, Args&&... args)
{
    // 使用formatMessage进行参数连接（不支持printf风格的格式化）
    std::string message = detail::formatMessage(format, std::forward<Args>(args)...);
    Logger::getInstance().log(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                              message);
}

// 日志一次函数
template <typename... Args>
inline void logOnce(const LogContext& ctx, LogLevel level, Args&&... args)
{
    std::string message = detail::formatMessage(std::forward<Args>(args)...);
    Logger::getInstance().logOnce(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                                   message);
}

// 控制频率日志函数
template <typename... Args>
inline void logCtrlHz(const LogContext& ctx, LogLevel level, int hz, Args&&... args)
{
    std::string message = detail::formatMessage(std::forward<Args>(args)...);
    Logger::getInstance().logCtrlHz(ctx.file(), ctx.function(), ctx.line(), static_cast<int>(level),
                                     hz, message);
}

// 定时器辅助类
class TimerScope
{
  public:
    TimerScope(const char* file, const char* function, int line, const std::string& message)
        : file_(file), function_(function), line_(line)
    {
        Timer::getInstance().begin(file_, function_, line_, message);
    }

    TimerScope(const char* file, const char* function, int line, int message)
        : file_(file), function_(function), line_(line)
    {
        Timer::getInstance().begin(file_, function_, line_, message);
    }

    ~TimerScope()
    {
        Timer::getInstance().end(file_, function_, line_, 0, "");
    }

    void end(LogLevel level, const std::string& message)
    {
        Timer::getInstance().end(file_, function_, line_, static_cast<int>(level), message);
    }

    void end(LogLevel level, int message)
    {
        Timer::getInstance().end(file_, function_, line_, static_cast<int>(level), message);
    }

  private:
    const char* file_;
    const char* function_;
    int line_;
};

}  // namespace toolsLib

// 便捷宏：用于创建LogContext（保留宏以便于使用，但更简洁）
#define TOOLS_LOG_CTX() toolsLib::LogContext(__FILE__, __FUNCTION__, __LINE__)

// 日志便捷函数（使用内联函数替代宏）
// 格式化日志宏：使用 printf 风格的格式化字符串（推荐，使用频率高）
// 流式连接日志宏：使用 << 操作符连接参数（使用频率低，名称较长）
#define LOG_NORM(...) toolsLib::Logger::getInstance().log(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::NORM), __VA_ARGS__)
#define LOG_INFO(...) toolsLib::Logger::getInstance().log(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::INFO), __VA_ARGS__)
#define LOG_WARNING(...) toolsLib::Logger::getInstance().log(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::WARNING), __VA_ARGS__)
#define LOG_ERROR(...) toolsLib::Logger::getInstance().log(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::ERROR), __VA_ARGS__)

// 流式连接日志宏：使用 << 操作符连接参数（如 "Value: ", value, ", Name: ", name）
#define LOG_NORM_STREAM(...) toolsLib::logCore(TOOLS_LOG_CTX(), toolsLib::LogLevel::NORM, __VA_ARGS__)
#define LOG_INFO_STREAM(...) toolsLib::logCore(TOOLS_LOG_CTX(), toolsLib::LogLevel::INFO, __VA_ARGS__)
#define LOG_WARNING_STREAM(...) \
    toolsLib::logCore(TOOLS_LOG_CTX(), toolsLib::LogLevel::WARNING, __VA_ARGS__)
#define LOG_ERROR_STREAM(...) toolsLib::logCore(TOOLS_LOG_CTX(), toolsLib::LogLevel::ERROR, __VA_ARGS__)
// 格式化日志宏（无时间戳版本）
#define LOG_INFO_NOTIME(...) toolsLib::Logger::getInstance().log(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::INFO_NOTIME), __VA_ARGS__)
#define LOG_WARNING_NOTIME(...) toolsLib::Logger::getInstance().log(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::WARNING_NOTIME), __VA_ARGS__)
#define LOG_ERROR_NOTIME(...) toolsLib::Logger::getInstance().log(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::ERROR_NOTIME), __VA_ARGS__)

// 流式连接日志宏（无时间戳版本）
#define LOG_INFO_STREAM_NOTIME(...) \
    toolsLib::logCore(TOOLS_LOG_CTX(), toolsLib::LogLevel::INFO_NOTIME, __VA_ARGS__)
#define LOG_WARNING_STREAM_NOTIME(...) \
    toolsLib::logCore(TOOLS_LOG_CTX(), toolsLib::LogLevel::WARNING_NOTIME, __VA_ARGS__)
#define LOG_ERROR_STREAM_NOTIME(...) \
    toolsLib::logCore(TOOLS_LOG_CTX(), toolsLib::LogLevel::ERROR_NOTIME, __VA_ARGS__)

#define LOG_NORM_ONCE(...) \
    toolsLib::logOnce(TOOLS_LOG_CTX(), toolsLib::LogLevel::NORM, __VA_ARGS__)
#define LOG_INFO_ONCE(...) \
    toolsLib::logOnce(TOOLS_LOG_CTX(), toolsLib::LogLevel::INFO, __VA_ARGS__)
#define LOG_WARNING_ONCE(...) \
    toolsLib::logOnce(TOOLS_LOG_CTX(), toolsLib::LogLevel::WARNING, __VA_ARGS__)
#define LOG_ERROR_ONCE(...) \
    toolsLib::logOnce(TOOLS_LOG_CTX(), toolsLib::LogLevel::ERROR, __VA_ARGS__)
#define LOG_INFO_ONCE_NOTIME(...) \
    toolsLib::logOnce(TOOLS_LOG_CTX(), toolsLib::LogLevel::INFO_NOTIME, __VA_ARGS__)
#define LOG_WARNING_ONCE_NOTIME(...) \
    toolsLib::logOnce(TOOLS_LOG_CTX(), toolsLib::LogLevel::WARNING_NOTIME, __VA_ARGS__)
#define LOG_ERROR_ONCE_NOTIME(...) \
    toolsLib::logOnce(TOOLS_LOG_CTX(), toolsLib::LogLevel::ERROR_NOTIME, __VA_ARGS__)

#define LOG_NORM_CTRL(hz, ...) \
    toolsLib::logCtrlHz(TOOLS_LOG_CTX(), toolsLib::LogLevel::NORM, hz, __VA_ARGS__)
// 格式化日志宏（控频版本）
#define LOG_NORM_CTRL(hz, ...) \
    toolsLib::Logger::getInstance().logCtrlHz(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::NORM), hz, __VA_ARGS__)
#define LOG_INFO_CTRL(hz, ...) \
    toolsLib::Logger::getInstance().logCtrlHz(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::INFO), hz, __VA_ARGS__)
#define LOG_WARNING_CTRL(hz, ...) \
    toolsLib::Logger::getInstance().logCtrlHz(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::WARNING), hz, __VA_ARGS__)
#define LOG_ERROR_CTRL(hz, ...) \
    toolsLib::Logger::getInstance().logCtrlHz(__FILE__, __FUNCTION__, __LINE__, \
                                        static_cast<int>(toolsLib::LogLevel::ERROR), hz, __VA_ARGS__)

// 流式连接日志宏（控频版本）
#define LOG_INFO_CTRL_STREAM(hz, ...) \
    toolsLib::logCtrlHz(TOOLS_LOG_CTX(), toolsLib::LogLevel::INFO, hz, __VA_ARGS__)
#define LOG_WARNING_CTRL_STREAM(hz, ...) \
    toolsLib::logCtrlHz(TOOLS_LOG_CTX(), toolsLib::LogLevel::WARNING, hz, __VA_ARGS__)
#define LOG_ERROR_CTRL_STREAM(hz, ...) \
    toolsLib::logCtrlHz(TOOLS_LOG_CTX(), toolsLib::LogLevel::ERROR, hz, __VA_ARGS__)
#define LOG_INFO_CTRL_STREAM_NOTIME(hz, ...) \
    toolsLib::logCtrlHz(TOOLS_LOG_CTX(), toolsLib::LogLevel::INFO_NOTIME, hz, __VA_ARGS__)
#define LOG_WARNING_CTRL_STREAM_NOTIME(hz, ...) \
    toolsLib::logCtrlHz(TOOLS_LOG_CTX(), toolsLib::LogLevel::WARNING_NOTIME, hz, __VA_ARGS__)
#define LOG_ERROR_CTRL_STREAM_NOTIME(hz, ...) \
    toolsLib::logCtrlHz(TOOLS_LOG_CTX(), toolsLib::LogLevel::ERROR_NOTIME, hz, __VA_ARGS__)

// 定时器便捷宏
#define TIMER_BEGIN(msg) \
    toolsLib::Timer::getInstance().begin(__FILE__, __FUNCTION__, __LINE__, msg)
#define TIMER_END(level, msg) \
    toolsLib::Timer::getInstance().end(__FILE__, __FUNCTION__, __LINE__, static_cast<int>(level), msg)

// 其他便捷函数（使用内联函数替代宏）
inline void SAVE_LOG(const std::string& savePath)
{
    toolsLib::Logger::getInstance().setLogPath(savePath.c_str());
}

inline void SET_SAVE(bool save)
{
    toolsLib::Logger::getInstance().setSaveLog(save);
}

inline void PURE_LOG(bool pure)
{
    toolsLib::Logger::getInstance().setPureLog(pure);
}

// 日志分割功能
inline void SET_LOG_SPLIT(bool enable)
{
    toolsLib::Logger::getInstance().setLogSplit(enable);
}

inline void SET_LOG_SPLIT_BY_TIME(int64_t durationMs)
{
    toolsLib::Logger::getInstance().setLogSplitByTime(durationMs);
}

inline void SET_LOG_AUTO_COMPRESS(bool enable)
{
    toolsLib::Logger::getInstance().setLogAutoCompress(enable);
}

inline void SPLIT_LOG()
{
    toolsLib::Logger::getInstance().splitLog();
}

template <typename T, typename... Args>
inline std::shared_ptr<T> GET_INSTANCE(Args&&... args)
{
    return toolsLib::singletonBase<T>::getInstance(std::forward<Args>(args)...);
}

template <typename T>
inline void DEL_INSTANCE()
{
    toolsLib::singletonBase<T>::deleteInstance();
}

inline void LOAD_YAML(const std::string& fileName)
{
    toolsLib::getParam::getInstance().loadYamlFile(__FILE__, __FUNCTION__, __LINE__, fileName);
}

template <typename T>
inline void GET_PARAM(const std::string& name, T& value)
{
    toolsLib::getParam::getInstance().getParameter(__FILE__, __FUNCTION__, __LINE__, name, value);
}

#ifdef HAVE_ROS
inline void SET_IP(const std::string& ip, int port)
{
    toolsLib::publish::getInstance(ip, port);
}

template <typename T>
inline void SEND_DATA(const T& data)
{
    toolsLib::publish::getInstance().sendData(data);
}
#endif

// Bash操作便捷函数
inline bool BASH(const std::string& cmd, std::string& result)
{
    return toolsLib::Bash::getInstance().shCmd(cmd, result);
}

inline bool MV(const std::string& source, const std::string& target)
{
    return toolsLib::Bash::getInstance().mvFile(source, target);
}

inline bool CP(const std::string& source, const std::string& target)
{
    return toolsLib::Bash::getInstance().cpFile(source, target);
}

inline bool RM(const std::string& source)
{
    return toolsLib::Bash::getInstance().rmFile(source);
}

inline bool MKDIR(const std::string& source)
{
    return toolsLib::Bash::getInstance().mkDir(source);
}

inline bool RMDIR(const std::string& source)
{
    return toolsLib::Bash::getInstance().rmDir(source);
}

inline bool TOUCH(const std::string& source)
{
    return toolsLib::Bash::getInstance().touch(source);
}

inline bool GZIP(const std::string& source)
{
    return toolsLib::Bash::getInstance().gzip(source);
}

inline bool ZIP(const std::string& file, const std::string& zipName)
{
    return toolsLib::Bash::getInstance().zip(file, zipName);
}

inline void LS(const std::string& directory, std::vector<std::string>& fileList)
{
    toolsLib::Bash::getInstance().list(directory, fileList);
}

inline void GET_NAME(const std::string& file, std::string& name)
{
    toolsLib::Bash::getInstance().getName(file, name);
}

inline bool COMPARE_DIR(const std::string& dir1,
                        const std::string& dir2,
                        std::vector<std::string>& result)
{
    return toolsLib::File::getInstance().extractSameNameFile(dir1, dir2, result);
}

inline bool GET_FILE(const std::string& csv,
                     const std::string& source,
                     const std::string& target)
{
    return toolsLib::File::getInstance().filtrateFileFromCSV(csv, source, target);
}

// 图像操作便捷函数
inline cv::Mat LOAD_IMAGE(const std::string& file_path)
{
    return toolsLib::ImageLoader().loadImage(file_path);
}

inline cv::Mat LOAD_FIRST_IMAGE(const std::string& directory_path)
{
    return toolsLib::ImageLoader().loadFirstImage(directory_path);
}

inline bool SAVE_IMAGE(const cv::Mat& image, const std::string& file_path)
{
    return toolsLib::ImageSaver().saveImage(image, file_path);
}

inline void SHOW_IMAGE(const cv::Mat& image, const std::string& window_name)
{
    static toolsLib::ImageViewer viewer;
    viewer.showImage(image, window_name);
}

inline void SHOW_BIND_IMAGE(const cv::Mat& image, const std::string& window_name, const std::string& bind_name)
{
    static toolsLib::ImageViewer viewer;
    viewer.showBindImage(image, window_name, bind_name);
}

inline void DESTROY_DISPLAY(const std::string& window_name)
{
    static toolsLib::ImageViewer viewer;
    viewer.destroyDisplay(window_name);
}

inline void DESTROY_ALL_DISPLAY()
{
    static toolsLib::ImageViewer viewer;
    viewer.destroyAllDisplay();
}

inline void DESTROY_BIND_IMAGE(const std::string& bind_name)
{
    static toolsLib::ImageViewer viewer;
    viewer.destroyBindImage(bind_name);
}

inline cv::Mat COMPARE_IMAGES(const cv::Mat& image1, const cv::Mat& image2)
{
    return toolsLib::ImageComparator().compareImages(image1, image2);
}

inline void COMPARE_IMAGES_DISPLAY(const cv::Mat& image1, const cv::Mat& image2, const std::string& bind_name)
{
    static toolsLib::ImageComparator comparator;
    comparator.compareImagesDisplay(image1, image2, bind_name);
}

inline void COMPARE_DISPLAY_DESTROY(const std::string& bind_name)
{
    static toolsLib::ImageComparator comparator;
    comparator.compareDisplayDestory(bind_name);
}

